package com.simen.hellobytes;

import com.simen.hellobytes.exception.UriParserException;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Created by Simen.
 * @date 创建日期 2018/11/11 19:42
 * @modify 修改者 Simen
 */
public class UriHelper {

    private String url;// http://example.com/a/b/c?test=123
    private String schema;// http://
    private String host;// example.com
    private String path;// /a/b/c
    private String pathBody;// /a/b/c?test=123
    private Map<String, String> params = new HashMap<String, String>();

    private UriHelper(String url) {
        this.url = url;
    }

    public static UriHelper parse(String url) throws UriParserException {
        if (!URLUtil.isNetworkUrl(url)) {
            throw new UriParserException(url + " is not network url");
        }

        UriHelper uriHelper = new UriHelper(url);

        int startPoi = 0;
        if (url.startsWith("https")) {
            uriHelper.setSchema("https");
            startPoi = 8;
        } else {
            uriHelper.setSchema("http");
            startPoi = 7;
        }

        int firstPoiSplit = url.indexOf("/", startPoi);

        if (firstPoiSplit == -1) {
            uriHelper.setHost(url.substring(startPoi));
            return uriHelper;
        } else {
            uriHelper.setHost(url.substring(startPoi, firstPoiSplit));
        }

        uriHelper.setPathBody(url.substring(firstPoiSplit));

        int paramsFirstIndex = url.indexOf("?", firstPoiSplit);
        if (paramsFirstIndex == -1) {
            uriHelper.setPath(url.substring(firstPoiSplit));
            return uriHelper;
        }

        uriHelper.setPath(url.substring(firstPoiSplit, paramsFirstIndex));

        String[] paramsArray = url.substring(paramsFirstIndex + 1).split("&");
        for (int i = 0; i < paramsArray.length; i++) {
            int indexSplit = paramsArray[i].indexOf("=");

            if (indexSplit != -1 && (indexSplit + 1) != paramsArray[i].length()) {
                Map<String, String> params = uriHelper.getParams();

                params.put(paramsArray[i].substring(0, indexSplit),
                        paramsArray[i].substring(indexSplit + 1));
            }
        }

        return uriHelper;
    }

    /**
     * @param pathUrl 支持相对路径url(比如：/path?a=b)或绝对路径url(比如：http://www.sample.com/path?a=b)
     * @return 返回解析出的KV请求参数值
     */
    public static Map<String, String> getParamsFromPathUrl(String pathUrl) {
        int paramsFirstIndex = pathUrl.indexOf("?");
        if (paramsFirstIndex == -1) {
            return null;
        }
        Map<String, String> params = new HashMap<String, String>();
        String[] paramsArray = pathUrl.substring(paramsFirstIndex + 1).split("&");
        for (int i = 0; i < paramsArray.length; i++) {
            int indexSplit = paramsArray[i].indexOf("=");

            if (indexSplit != -1 && (indexSplit + 1) != paramsArray[i].length()) {
                params.put(paramsArray[i].substring(0, indexSplit),
                        paramsArray[i].substring(indexSplit + 1));
            }
        }

        return params;
    }

    void setSchema(String schema) {
        this.schema = schema;
    }

    void setHost(String host) {
        this.host = host;
    }

    void setPath(String path) {
        this.path = path;
    }

    public void setParams(Map<String, String> params) {
        this.params = params;
    }

    public String getUrl() {
        return url;
    }

    public String getHost() {
        return host;
    }

    public String getPath() {
        return path;
    }

    public String getSchema() {
        return schema;
    }

    public String getParam(String key) {
        return params.get(key);
    }

    public Map<String, String> getParams() {
        return params;
    }

    void setPathBody(String pathBody) {
        this.pathBody = pathBody;
    }

    public String getPathBody() {
        return pathBody;
    }

    @Override
    public String toString() {
        return url;
    }

    public String toFieldString() {
        return schema + "://" + host + (pathBody == null ? "" : pathBody);
    }
}
